Categories
TypeScript

JavaScript Object Features in TypeScript — Inheritance and Classes

Spread the love

TypeScript is a natural extension of JavaScript that’s used in many projects in place of JavaScript.

However, not everyone knows how it actually works.

In this article, we’ll look at accessing overridden prototype methods and the class syntax.

Accessing Overridden Prototype Methods

Even if we override methods in a constructor function that inherits from a parent constructor, we can still access the parent constructor’s implementation of the constructor.

For instance, if we have:

const Animal = function(name) {
  this.name = name;
};
Animal.prototype.toString = function() {
  return `name: ${this.name}`;
};

const Dog = function(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
};
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
Dog.prototype.toString = function() {
  return `name: ${this.name}, breed: ${this.breed}`;
};

Then we can call the parent constructor’s method to replace part of Dog‘s prototype’s toString method by writing:

const Animal = function(name) {
  this.name = name;
};

Animal.prototype.toString = function() {
  return `name: ${this.name}`;
};

const Dog = function(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
};

Object.setPrototypeOf(Dog.prototype, Animal.prototype);

Dog.prototype.toString = function() {
  const name = Animal.prototype.toString.call(this, this.name);
  return `${name}, breed: ${this.breed}`;
};

We reused the Animal.prototype ‘s toString method to form part of Dog.prototype ‘s toString method.

This way, we don’t have to repeat any code.

Defining Static Properties and Methods

We can define static methods and properties as properties on the function itself.

We can do that because functions are just ordinary objects.

For instance, we can write:

const Animal = function(name) {
  this.name = name;
};
Animal.type = 'animal';

console.log(Animal.type);

Then we defined a static type property on Animal.

We can then access it by referencing Animal.type .

JavaScript Classes

JavaScript class is a syntax that eases the transition from other popular programming languages.

However, behind the scenes, it’s just a combination of constructors and prototypes.

There are some differences between a JavaScript class and other class-based languages like Java.

All instance variables are public.

Also, we can return any object we want in the constructor and we return that object when we invoke the class with new .

Like constructor functions, it’s invoked with the new keyword.

For instance, we can define a class by writing:

class Animal {
  constructor(name) {
    this.name = name;
  }

  toString() {
    return `name: ${this.name}`;
  }
}

We have an Animal constructor that returns an Animal instance, with the name property and the toString method.

Then if we create an Animal instance by writing:

const animal = new Animal('joe');

If we look at the content of animal , we see the name property in animal .

In the __proto__ property of it, we see the toString method.

To create a subclass that inherits from a parent class, we use the extends keyword.

For instance, we can write:

class Animal {
  constructor(name) {
    this.name = name;
  }

  toString() {
    return `name: ${this.name}`;
  }
}

class Dog extends Animal {}

We create a subclass of Animal which inherits from the Animal parent class.

Then when we write:

const dog = new Dog('joe');

and call toString:

console.log(dog.toString());

We get:

name: joe

from the console log.

The toString method is inherited from the Animal class.

To call the parent constructor, we use the super keyword.

And if we want to call a parent constructor’s methods, we use the same keyword followed by a dot plus the method name.

For instance, if we want to add constructor and a toString method to Dog , we can write:

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  toString() {
    const name = super.toString();
    return `${name} breed: ${this.breed}`;
  }
}

Given the Animal class we have before, we can call Animal‘s toString by writing calling super.toString(); .

We call the constructor of the parent by using the super keyword as we did in Dog ‘s constructor .

The super call must be before anything else in the constructor body.

The extends keyword indicates that our Dog class inherits members from the Animal class.

So when we create a new Dog instance by writing:

const dog = new Dog('joe', 'lab');
console.log(dog.toString());

and then call toString on it, we get:

name: joe breed: lab

from the console log.

Conclusion

The class syntax makes transitioning from other object-oriented languages easier.

Also, it cleans up the constructor code by putting them in one neat package.

We can also call the parent constructor in a much cleaner fashion.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *